package edu.ynu.se.xiecheng.achitectureclass.digitalagriculture.utils;

import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5Utils {

    public static String DEFAULT_KEY = "adszxcvaf";

    public static Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    private static final char[] HEX_DIGITS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102};

    /**
     * 通用MD5加密
     * 设计原则体现：
     * 1. 单一职责原则(SRP) - 方法只负责MD5加密
     * 2. 关注点分离 - 加密逻辑与其他业务逻辑分离
     * 3. 防御性编程 - 处理null输入，避免异常
     */
    public static String standardSign(String content) {
        if (content == null) {
            return null; // 处理null输入
        }

        try {
            return standardSign(content.getBytes(DEFAULT_CHARSET));
        } catch (NoSuchAlgorithmException e) {
            return null; // 处理异常情况
        }
    }

    public static String standardSign(byte[] input) throws NoSuchAlgorithmException {
        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        messageDigest.update(input);
        byte[] buffer = messageDigest.digest();
        return bytesToStr(buffer);
    }

    private static String bytesToStr(byte[] buffer) {
        char[] resultBuffer = new char[32];
        int i = 0;
        int j = 0;
        while (true) {
            if (i >= 16)
                return new String(resultBuffer);
            int k = buffer[i];
            int m = j + 1;
            resultBuffer[j] = HEX_DIGITS[(0xF & k >>> 4)];
            j = m + 1;
            resultBuffer[m] = HEX_DIGITS[(k & 0xF)];
            i++;
        }
    }

    /**
     * MD5方法
     * 设计原则体现：
     * 1. 单一职责原则(SRP) - 方法只负责生成MD5密文
     * 2. 关注点分离 - 加密逻辑与其他业务逻辑分离
     */
    public static String md5(String text, String key) {
        //加密后的字符串,经过两次混淆加密
        String encodeStr = standardSign(text + key);
        encodeStr = standardSign(key + encodeStr);
        return encodeStr;
    }

    public static String md5(String text) {
        return md5(text, DEFAULT_KEY);
    }

    /**
     * MD5验证方法
     * 设计原则体现：
     * 1. 单一职责原则(SRP) - 方法只负责验证MD5
     * 2. 关注点分离 - 验证逻辑与其他业务逻辑分离
     */
    public static boolean verify(String text, String md5) {
        //根据传入的密钥进行验证
        return verify(text, DEFAULT_KEY, md5);
    }

    /**
     * MD5验证方法
     * 设计原则体现：
     * 1. 单一职责原则(SRP) - 方法只负责验证MD5
     * 2. 关注点分离 - 验证逻辑与其他业务逻辑分离
     */
    public static boolean verify(String text, String key, String md5) {
        //根据传入的密钥进行验证
        String md5Text = md5(text, key);
        if (md5Text.equalsIgnoreCase(md5)) {
            System.out.println("MD5验证通过");
            return true;
        }

        return false;
    }

    public static void main(String[] args) throws Exception {
        System.out.println(MD5Utils.md5("asd123"));
    }
}